Micron Document
--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
| SparkN0de-git | SparkN0de |
--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------

Node / ReticulumProjects / MeshChatX.git / files / tests / backend / test_security_path_jail_regressions.py

Displaying Raw • Download


tests/backend/test_security_path_jail_regressions.py c0b0ddffd735a0d007c1be9a5e8563ec42fdafc0 (c0b0ddff) Text, 9.39 KB

T8b949e# SPDX-License-Identifier: 0BSD

T8b949e"""Regression tests for HIGH/CRITICAL path jail and client-IP fixes."""

Tff7b72from T7ee787__future__ Tff7b72import Te6edf3annotations

Tff7b72import T7ee787os
Tff7b72from T7ee787types Tff7b72import Te6edf3SimpleNamespace
Tff7b72from T7ee787unittestT7ee787.T7ee787mock Tff7b72import Te6edf3MagicMock

Tff7b72import T7ee787pytest

Tff7b72from T7ee787meshchatxT7ee787.T7ee787srcT7ee787.T7ee787backendT7ee787.T7ee787app_security_settings Tff7b72import Tb4b4b4(
Te6edf3get_trusted_proxy_cidrsTb4b4b4,
Te6edf3save_app_security_settingsTb4b4b4,
Tb4b4b4)
Tff7b72from T7ee787meshchatxT7ee787.T7ee787srcT7ee787.T7ee787backendT7ee787.T7ee787database Tff7b72import Te6edf3Database
Tff7b72from T7ee787meshchatxT7ee787.T7ee787srcT7ee787.T7ee787backendT7ee787.T7ee787identity_manager Tff7b72import Te6edf3IdentityManager
Tff7b72from T7ee787meshchatxT7ee787.T7ee787srcT7ee787.T7ee787backendT7ee787.T7ee787meshchat_utils Tff7b72import Te6edf3normalize_identity_storage_hash
Tff7b72from T7ee787meshchatxT7ee787.T7ee787srcT7ee787.T7ee787backendT7ee787.T7ee787plugin_guard Tff7b72import Te6edf3PluginSecurityError
Tff7b72from T7ee787meshchatxT7ee787.T7ee787srcT7ee787.T7ee787backendT7ee787.T7ee787plugin_manager Tff7b72import Te6edf3PluginManager
Tff7b72from T7ee787meshchatxT7ee787.T7ee787srcT7ee787.T7ee787backendT7ee787.T7ee787rncp_handler Tff7b72import Te6edf3RNCPHandler
Tff7b72from T7ee787meshchatxT7ee787.T7ee787srcT7ee787.T7ee787path_utils Tff7b72import Tb4b4b4(
Te6edf3is_path_within_dirTb4b4b4,
Te6edf3request_client_ipTb4b4b4,
Te6edf3resolve_path_under_dirTb4b4b4,
Te6edf3safe_path_under_dirTb4b4b4,
Tb4b4b4)


Tff7b72def Td2a8fftest_normalize_identity_storage_hash_rejects_traversalTb4b4b4(Tb4b4b4)Tb4b4b4:
Tff7b72assert Te6edf3normalize_identity_storage_hashTb4b4b4(Ta5d6ff"Ta5d6ff../../tmp/targetTa5d6ff"Tb4b4b4) Tff7b72== Ta5d6ff"Ta5d6ff"
Tff7b72assert Te6edf3normalize_identity_storage_hashTb4b4b4(Ta5d6ff"Ta5d6ffnot-a-hashTa5d6ff"Tb4b4b4) Tff7b72== Ta5d6ff"Ta5d6ff"
Tff7b72assert Te6edf3normalize_identity_storage_hashTb4b4b4(Ta5d6ff"Ta5d6ffabTa5d6ff" Tff7b72* T79c0ff16Tb4b4b4) Tff7b72== Ta5d6ff"Ta5d6ffabTa5d6ff" Tff7b72* T79c0ff16


Tff7b72def Td2a8fftest_delete_identity_rejects_path_traversalTb4b4b4(Te6edf3tmp_pathTb4b4b4)Tb4b4b4:
Te6edf3manager Tff7b72= Te6edf3IdentityManagerTb4b4b4(Tffa657strTb4b4b4(Te6edf3tmp_pathTb4b4b4)Tb4b4b4)
Te6edf3victim Tff7b72= Te6edf3tmp_path Tff7b72/ Ta5d6ff"Ta5d6ffvictim_dirTa5d6ff"
Te6edf3victimTff7b72.Td2a8ffmkdirTb4b4b4(Tb4b4b4)
Te6edf3marker Tff7b72= Te6edf3victim Tff7b72/ Ta5d6ff"Ta5d6ffkeep.txtTa5d6ff"
Te6edf3markerTff7b72.Td2a8ffwrite_textTb4b4b4(Ta5d6ff"Ta5d6ffsafeTa5d6ff"Tb4b4b4)
Tff7b72with Te6edf3pytestTff7b72.Td2a8ffraisesTb4b4b4(Tf85149ValueErrorTb4b4b4, Te6edf3matchTff7b72=Ta5d6ff"Ta5d6ffInvalid identity hashTa5d6ff"Tb4b4b4)Tb4b4b4:
Te6edf3managerTff7b72.Td2a8ffdelete_identityTb4b4b4(Ta5d6ff"Ta5d6ff../../victim_dirTa5d6ff"Tb4b4b4, Te6edf3current_identity_hashTff7b72=Tff7b72NoneTb4b4b4)
Tff7b72assert Te6edf3markerTff7b72.Td2a8ffexistsTb4b4b4(Tb4b4b4)


Tff7b72def Td2a8fftest_delete_identity_rejects_wrong_length_hexTb4b4b4(Te6edf3tmp_pathTb4b4b4)Tb4b4b4:
T8b949e"""Hash length must be enforced even when the path would stay in-tree."""
Te6edf3manager Tff7b72= Te6edf3IdentityManagerTb4b4b4(Tffa657strTb4b4b4(Te6edf3tmp_pathTb4b4b4)Tb4b4b4)
Te6edf3short_hash Tff7b72= Ta5d6ff"Ta5d6ffabTa5d6ff" Tff7b72* T79c0ff15
Te6edf3target Tff7b72= Te6edf3tmp_path Tff7b72/ Ta5d6ff"Ta5d6ffidentitiesTa5d6ff" Tff7b72/ Te6edf3short_hash
Te6edf3targetTff7b72.Td2a8ffmkdirTb4b4b4(Te6edf3parentsTff7b72=Tff7b72TrueTb4b4b4)
Tb4b4b4(Te6edf3target Tff7b72/ Ta5d6ff"Ta5d6ffidentityTa5d6ff"Tb4b4b4)Tff7b72.Td2a8ffwrite_bytesTb4b4b4(Ta5d6ffbTa5d6ff"Ta5d6ffxTa5d6ff"Tb4b4b4)
Tff7b72with Te6edf3pytestTff7b72.Td2a8ffraisesTb4b4b4(Tf85149ValueErrorTb4b4b4, Te6edf3matchTff7b72=Ta5d6ff"Ta5d6ffInvalid identity hashTa5d6ff"Tb4b4b4)Tb4b4b4:
Te6edf3managerTff7b72.Td2a8ffdelete_identityTb4b4b4(Te6edf3short_hashTb4b4b4, Te6edf3current_identity_hashTff7b72=Tff7b72NoneTb4b4b4)
Tff7b72assert Te6edf3targetTff7b72.Td2a8ffexistsTb4b4b4(Tb4b4b4)


Tff7b72def Td2a8fftest_delete_identity_removes_only_canonical_dirTb4b4b4(Te6edf3tmp_pathTb4b4b4)Tb4b4b4:
Te6edf3manager Tff7b72= Te6edf3IdentityManagerTb4b4b4(Tffa657strTb4b4b4(Te6edf3tmp_pathTb4b4b4)Tb4b4b4)
Te6edf3identity_hash Tff7b72= Ta5d6ff"Ta5d6ffcdTa5d6ff" Tff7b72* T79c0ff16
Te6edf3target Tff7b72= Te6edf3tmp_path Tff7b72/ Ta5d6ff"Ta5d6ffidentitiesTa5d6ff" Tff7b72/ Te6edf3identity_hash
Te6edf3targetTff7b72.Td2a8ffmkdirTb4b4b4(Te6edf3parentsTff7b72=Tff7b72TrueTb4b4b4)
Tb4b4b4(Te6edf3target Tff7b72/ Ta5d6ff"Ta5d6ffidentityTa5d6ff"Tb4b4b4)Tff7b72.Td2a8ffwrite_bytesTb4b4b4(Ta5d6ffbTa5d6ff"Ta5d6ffxTa5d6ff"Tb4b4b4)
Tff7b72assert Te6edf3managerTff7b72.Td2a8ffdelete_identityTb4b4b4(Te6edf3identity_hashTb4b4b4, Te6edf3current_identity_hashTff7b72=Tff7b72NoneTb4b4b4) Tff7b72is Tff7b72True
Tff7b72assert Tff7b72not Te6edf3targetTff7b72.Td2a8ffexistsTb4b4b4(Tb4b4b4)


Tff7b72def Td2a8fftest_backup_delete_rejects_prefix_collision_and_traversalTb4b4b4(Te6edf3tmp_pathTb4b4b4)Tb4b4b4:
Te6edf3db Tff7b72= Te6edf3DatabaseTb4b4b4(Tffa657strTb4b4b4(Te6edf3tmp_path Tff7b72/ Ta5d6ff"Ta5d6fft.dbTa5d6ff"Tb4b4b4)Tb4b4b4)
Te6edf3dbTff7b72.Td2a8ffinitializeTb4b4b4(Tb4b4b4)
Te6edf3storage Tff7b72= Tffa657strTb4b4b4(Te6edf3tmp_pathTb4b4b4)
Te6edf3backup_dir Tff7b72= Te6edf3osTff7b72.Td2a8ffpathTff7b72.Td2a8ffjoinTb4b4b4(Te6edf3storageTb4b4b4, Ta5d6ff"Ta5d6ffdatabase-backupsTa5d6ff"Tb4b4b4)
Te6edf3old_dir Tff7b72= Te6edf3osTff7b72.Td2a8ffpathTff7b72.Td2a8ffjoinTb4b4b4(Te6edf3storageTb4b4b4, Ta5d6ff"Ta5d6ffdatabase-backups_oldTa5d6ff"Tb4b4b4)
Te6edf3osTff7b72.Td2a8ffmakedirsTb4b4b4(Te6edf3backup_dirTb4b4b4, Te6edf3exist_okTff7b72=Tff7b72TrueTb4b4b4)
Te6edf3osTff7b72.Td2a8ffmakedirsTb4b4b4(Te6edf3old_dirTb4b4b4, Te6edf3exist_okTff7b72=Tff7b72TrueTb4b4b4)
Te6edf3secret Tff7b72= Te6edf3osTff7b72.Td2a8ffpathTff7b72.Td2a8ffjoinTb4b4b4(Te6edf3old_dirTb4b4b4, Ta5d6ff"Ta5d6ffsecret.zipTa5d6ff"Tb4b4b4)
Tff7b72with Tffa657openTb4b4b4(Te6edf3secretTb4b4b4, Ta5d6ff"Ta5d6ffwbTa5d6ff"Tb4b4b4) Tff7b72as Te6edf3handleTb4b4b4:
Te6edf3handleTff7b72.Td2a8ffwriteTb4b4b4(Ta5d6ffbTa5d6ff"Ta5d6ffPKTa5d6ff"Tb4b4b4)
Tff7b72with Te6edf3pytestTff7b72.Td2a8ffraisesTb4b4b4(Tf85149ValueErrorTb4b4b4, Te6edf3matchTff7b72=Ta5d6ff"Ta5d6ffInvalid pathTa5d6ff"Tb4b4b4)Tb4b4b4:
Te6edf3dbTff7b72.Td2a8ffdelete_snapshot_or_backupTb4b4b4(
Te6edf3storageTb4b4b4,
Ta5d6ff"Ta5d6ff../database-backups_old/secret.zipTa5d6ff"Tb4b4b4,
Te6edf3is_backupTff7b72=Tff7b72TrueTb4b4b4,
Tb4b4b4)
Tff7b72assert Te6edf3osTff7b72.Td2a8ffpathTff7b72.Td2a8ffexistsTb4b4b4(Te6edf3secretTb4b4b4)
Te6edf3dbTff7b72.Td2a8ffclose_allTb4b4b4(Tb4b4b4)


Tff7b72def Td2a8fftest_safe_path_under_dir_collapses_traversal_to_basenameTb4b4b4(Te6edf3tmp_pathTb4b4b4)Tb4b4b4:
Te6edf3active Tff7b72= Te6edf3tmp_path Tff7b72/ Ta5d6ff"Ta5d6ffidentitiesTa5d6ff" Tff7b72/ Tb4b4b4(Ta5d6ff"Ta5d6ffaaTa5d6ff" Tff7b72* T79c0ff16Tb4b4b4) Tff7b72/ Ta5d6ff"Ta5d6ffdatabase-backupsTa5d6ff"
Te6edf3other Tff7b72= Te6edf3tmp_path Tff7b72/ Ta5d6ff"Ta5d6ffidentitiesTa5d6ff" Tff7b72/ Tb4b4b4(Ta5d6ff"Ta5d6ffbbTa5d6ff" Tff7b72* T79c0ff16Tb4b4b4) Tff7b72/ Ta5d6ff"Ta5d6ffdatabase-backupsTa5d6ff"
Te6edf3activeTff7b72.Td2a8ffmkdirTb4b4b4(Te6edf3parentsTff7b72=Tff7b72TrueTb4b4b4)
Te6edf3otherTff7b72.Td2a8ffmkdirTb4b4b4(Te6edf3parentsTff7b72=Tff7b72TrueTb4b4b4)
Te6edf3secret Tff7b72= Te6edf3other Tff7b72/ Ta5d6ff"Ta5d6ffsecret.zipTa5d6ff"
Te6edf3secretTff7b72.Td2a8ffwrite_bytesTb4b4b4(Ta5d6ffbTa5d6ff"Ta5d6ffPKTa5d6ff"Tb4b4b4)
T8b949e# Basename collapse must not resolve to the other identity's file.
Te6edf3resolved Tff7b72= Te6edf3safe_path_under_dirTb4b4b4(
Tffa657strTb4b4b4(Te6edf3activeTb4b4b4)Tb4b4b4,
Ta5d6ff"Ta5d6ff../../Ta5d6ff" Tff7b72+ Tb4b4b4(Ta5d6ff"Ta5d6ffbbTa5d6ff" Tff7b72* T79c0ff16Tb4b4b4) Tff7b72+ Ta5d6ff"Ta5d6ff/database-backups/secret.zipTa5d6ff"Tb4b4b4,
Tb4b4b4)
Tff7b72assert Te6edf3resolved Tff7b72== Te6edf3osTff7b72.Td2a8ffpathTff7b72.Td2a8ffrealpathTb4b4b4(Tffa657strTb4b4b4(Te6edf3active Tff7b72/ Ta5d6ff"Ta5d6ffsecret.zipTa5d6ff"Tb4b4b4)Tb4b4b4)
Tff7b72assert Te6edf3resolved Tff7b72!= Te6edf3osTff7b72.Td2a8ffpathTff7b72.Td2a8ffrealpathTb4b4b4(Tffa657strTb4b4b4(Te6edf3secretTb4b4b4)Tb4b4b4)


Tff7b72def Td2a8fftest_resolve_path_under_dir_allows_nested_safe_pathTb4b4b4(Te6edf3tmp_pathTb4b4b4)Tb4b4b4:
Te6edf3nested Tff7b72= Te6edf3tmp_path Tff7b72/ Ta5d6ff"Ta5d6ffsnapshotsTa5d6ff"
Te6edf3nestedTff7b72.Td2a8ffmkdirTb4b4b4(Tb4b4b4)
Te6edf3target Tff7b72= Te6edf3nested Tff7b72/ Ta5d6ff"Ta5d6ffsnap.zipTa5d6ff"
Te6edf3targetTff7b72.Td2a8ffwrite_bytesTb4b4b4(Ta5d6ffbTa5d6ff"Ta5d6ffPKTa5d6ff"Tb4b4b4)
Te6edf3resolved Tff7b72= Te6edf3resolve_path_under_dirTb4b4b4(Tffa657strTb4b4b4(Te6edf3nestedTb4b4b4)Tb4b4b4, Ta5d6ff"Ta5d6ffsnap.zipTa5d6ff"Tb4b4b4)
Tff7b72assert Te6edf3resolved Tff7b72== Te6edf3osTff7b72.Td2a8ffpathTff7b72.Td2a8ffrealpathTb4b4b4(Tffa657strTb4b4b4(Te6edf3targetTb4b4b4)Tb4b4b4)
Tff7b72assert Te6edf3resolve_path_under_dirTb4b4b4(Tffa657strTb4b4b4(Te6edf3nestedTb4b4b4)Tb4b4b4, Ta5d6ff"Ta5d6ff../outside.zipTa5d6ff"Tb4b4b4) Tff7b72is Tff7b72None


Tff7b72def Td2a8fftest_plugin_backend_entry_rejects_absolute_and_traversalTb4b4b4(Te6edf3tmp_pathTb4b4b4)Tb4b4b4:
Te6edf3manager Tff7b72= Te6edf3PluginManagerTb4b4b4(Tffa657strTb4b4b4(Te6edf3tmp_pathTb4b4b4)Tb4b4b4)
Tff7b72with Te6edf3pytestTff7b72.Td2a8ffraisesTb4b4b4(Tf85149ValueErrorTb4b4b4, Te6edf3matchTff7b72=Ta5d6ff"Ta5d6ffbackend.entry is invalidTa5d6ff"Tb4b4b4)Tb4b4b4:
Te6edf3managerTff7b72.Td2a8ff_validate_manifestTb4b4b4(
Tb4b4b4{
Ta5d6ff"Ta5d6ffidTa5d6ff"Tb4b4b4: Ta5d6ff"Ta5d6ffcom.example.evilTa5d6ff"Tb4b4b4,
Ta5d6ff"Ta5d6ffnameTa5d6ff"Tb4b4b4: Ta5d6ff"Ta5d6ffevilTa5d6ff"Tb4b4b4,
Ta5d6ff"Ta5d6ffversionTa5d6ff"Tb4b4b4: Ta5d6ff"Ta5d6ff1.0.0Ta5d6ff"Tb4b4b4,
Ta5d6ff"Ta5d6ffapiVersionTa5d6ff"Tb4b4b4: T79c0ff1Tb4b4b4,
Ta5d6ff"Ta5d6ffbackendTa5d6ff"Tb4b4b4: Tb4b4b4{Ta5d6ff"Ta5d6fftypeTa5d6ff"Tb4b4b4: Ta5d6ff"Ta5d6ffpythonTa5d6ff"Tb4b4b4, Ta5d6ff"Ta5d6ffentryTa5d6ff"Tb4b4b4: Ta5d6ff"Ta5d6ff/tmp/evil.pyTa5d6ff"Tb4b4b4}Tb4b4b4,
Tb4b4b4}Tb4b4b4,
Tb4b4b4)
Tff7b72with Te6edf3pytestTff7b72.Td2a8ffraisesTb4b4b4(Tf85149ValueErrorTb4b4b4, Te6edf3matchTff7b72=Ta5d6ff"Ta5d6ffbackend.entry is invalidTa5d6ff"Tb4b4b4)Tb4b4b4:
Te6edf3managerTff7b72.Td2a8ff_validate_manifestTb4b4b4(
Tb4b4b4{
Ta5d6ff"Ta5d6ffidTa5d6ff"Tb4b4b4: Ta5d6ff"Ta5d6ffcom.example.evil2Ta5d6ff"Tb4b4b4,
Ta5d6ff"Ta5d6ffnameTa5d6ff"Tb4b4b4: Ta5d6ff"Ta5d6ffevil2Ta5d6ff"Tb4b4b4,
Ta5d6ff"Ta5d6ffversionTa5d6ff"Tb4b4b4: Ta5d6ff"Ta5d6ff1.0.0Ta5d6ff"Tb4b4b4,
Ta5d6ff"Ta5d6ffapiVersionTa5d6ff"Tb4b4b4: T79c0ff1Tb4b4b4,
Ta5d6ff"Ta5d6ffbackendTa5d6ff"Tb4b4b4: Tb4b4b4{Ta5d6ff"Ta5d6fftypeTa5d6ff"Tb4b4b4: Ta5d6ff"Ta5d6ffwasmTa5d6ff"Tb4b4b4, Ta5d6ff"Ta5d6ffentryTa5d6ff"Tb4b4b4: Ta5d6ff"Ta5d6ff../escape.wasmTa5d6ff"Tb4b4b4}Tb4b4b4,
Tb4b4b4}Tb4b4b4,
Tb4b4b4)


Tff7b72def Td2a8fftest_plugin_python_entry_path_jails_to_install_treeTb4b4b4(Te6edf3tmp_pathTb4b4b4)Tb4b4b4:
Te6edf3manager Tff7b72= Te6edf3PluginManagerTb4b4b4(Tffa657strTb4b4b4(Te6edf3tmp_pathTb4b4b4)Tb4b4b4)
Te6edf3install Tff7b72= Te6edf3tmp_path Tff7b72/ Ta5d6ff"Ta5d6ffinstalledTa5d6ff" Tff7b72/ Ta5d6ff"Ta5d6ffcom.example.okTa5d6ff"
Te6edf3installTff7b72.Td2a8ffmkdirTb4b4b4(Te6edf3parentsTff7b72=Tff7b72TrueTb4b4b4)
Te6edf3entry Tff7b72= Te6edf3install Tff7b72/ Ta5d6ff"Ta5d6ffbackend.pyTa5d6ff"
Te6edf3entryTff7b72.Td2a8ffwrite_textTb4b4b4(Ta5d6ff"Ta5d6ffx = 1Tffea00\nTa5d6ff"Tb4b4b4)
Te6edf3outside Tff7b72= Te6edf3tmp_path Tff7b72/ Ta5d6ff"Ta5d6ffoutside.pyTa5d6ff"
Te6edf3outsideTff7b72.Td2a8ffwrite_textTb4b4b4(Ta5d6ff"Ta5d6ffx = 2Tffea00\nTa5d6ff"Tb4b4b4)
Te6edf3record Tff7b72= Te6edf3MagicMockTb4b4b4(Tb4b4b4)
Te6edf3recordTff7b72.Td2a8ffinstall_path Tff7b72= Tffa657strTb4b4b4(Te6edf3installTb4b4b4)
Te6edf3recordTff7b72.Td2a8ffmanifest Tff7b72= Tb4b4b4{Ta5d6ff"Ta5d6ffbackendTa5d6ff"Tb4b4b4: Tb4b4b4{Ta5d6ff"Ta5d6fftypeTa5d6ff"Tb4b4b4: Ta5d6ff"Ta5d6ffpythonTa5d6ff"Tb4b4b4, Ta5d6ff"Ta5d6ffentryTa5d6ff"Tb4b4b4: Ta5d6ff"Ta5d6ffbackend.pyTa5d6ff"Tb4b4b4}Tb4b4b4}
Tff7b72assert Te6edf3managerTff7b72.Td2a8ff_python_entry_pathTb4b4b4(Te6edf3recordTb4b4b4) Tff7b72== Te6edf3osTff7b72.Td2a8ffpathTff7b72.Td2a8ffrealpathTb4b4b4(Tffa657strTb4b4b4(Te6edf3entryTb4b4b4)Tb4b4b4)
Te6edf3recordTff7b72.Td2a8ffmanifest Tff7b72= Tb4b4b4{Ta5d6ff"Ta5d6ffbackendTa5d6ff"Tb4b4b4: Tb4b4b4{Ta5d6ff"Ta5d6fftypeTa5d6ff"Tb4b4b4: Ta5d6ff"Ta5d6ffpythonTa5d6ff"Tb4b4b4, Ta5d6ff"Ta5d6ffentryTa5d6ff"Tb4b4b4: Tffa657strTb4b4b4(Te6edf3outsideTb4b4b4)Tb4b4b4}Tb4b4b4}
Tff7b72with Te6edf3pytestTff7b72.Td2a8ffraisesTb4b4b4(Te6edf3PluginSecurityErrorTb4b4b4)Tb4b4b4:
Te6edf3managerTff7b72.Td2a8ff_python_entry_pathTb4b4b4(Te6edf3recordTb4b4b4)


Tff7b72def Td2a8fftest_plugin_wasm_resolve_does_not_delete_outside_installTb4b4b4(Te6edf3tmp_pathTb4b4b4)Tb4b4b4:
Te6edf3manager Tff7b72= Te6edf3PluginManagerTb4b4b4(Tffa657strTb4b4b4(Te6edf3tmp_pathTb4b4b4)Tb4b4b4)
Te6edf3install Tff7b72= Te6edf3tmp_path Tff7b72/ Ta5d6ff"Ta5d6ffinstalledTa5d6ff" Tff7b72/ Ta5d6ff"Ta5d6ffcom.example.wasmTa5d6ff"
Te6edf3installTff7b72.Td2a8ffmkdirTb4b4b4(Te6edf3parentsTff7b72=Tff7b72TrueTb4b4b4)
Te6edf3victim Tff7b72= Te6edf3tmp_path Tff7b72/ Ta5d6ff"Ta5d6ffvictim.txtTa5d6ff"
Te6edf3victimTff7b72.Td2a8ffwrite_textTb4b4b4(Ta5d6ff"Ta5d6ffdo-not-deleteTa5d6ff"Tb4b4b4)
Te6edf3record Tff7b72= Te6edf3MagicMockTb4b4b4(Tb4b4b4)
Te6edf3recordTff7b72.Td2a8ffid Tff7b72= Ta5d6ff"Ta5d6ffcom.example.wasmTa5d6ff"
Te6edf3recordTff7b72.Td2a8ffinstall_path Tff7b72= Tffa657strTb4b4b4(Te6edf3installTb4b4b4)
Te6edf3recordTff7b72.Td2a8ffmanifest Tff7b72= Tb4b4b4{Ta5d6ff"Ta5d6ffbackendTa5d6ff"Tb4b4b4: Tb4b4b4{Ta5d6ff"Ta5d6fftypeTa5d6ff"Tb4b4b4: Ta5d6ff"Ta5d6ffwasmTa5d6ff"Tb4b4b4, Ta5d6ff"Ta5d6ffentryTa5d6ff"Tb4b4b4: Tffa657strTb4b4b4(Te6edf3victimTb4b4b4)Tb4b4b4}Tb4b4b4}
Tff7b72with Te6edf3pytestTff7b72.Td2a8ffraisesTb4b4b4(Te6edf3PluginSecurityErrorTb4b4b4)Tb4b4b4:
Te6edf3managerTff7b72.Td2a8ff_resolve_backend_wasm_pathTb4b4b4(Te6edf3recordTb4b4b4)
Tff7b72assert Te6edf3victimTff7b72.Td2a8ffexistsTb4b4b4(Tb4b4b4)


Tf0883e@pytestTff7b72.Td2a8ffmarkTff7b72.Td2a8ffasyncio
Tff7b72async Tff7b72def Td2a8fftest_rncp_send_path_jails_and_blocks_identityTb4b4b4(Te6edf3tmp_pathTb4b4b4, Te6edf3monkeypatchTb4b4b4)Tb4b4b4:
Te6edf3handler Tff7b72= Te6edf3RNCPHandlerTb4b4b4(Te6edf3MagicMockTb4b4b4(Tb4b4b4)Tb4b4b4, Te6edf3MagicMockTb4b4b4(Tb4b4b4)Tb4b4b4, Tffa657strTb4b4b4(Te6edf3tmp_pathTb4b4b4)Tb4b4b4)
Te6edf3allowed Tff7b72= Te6edf3tmp_path Tff7b72/ Ta5d6ff"Ta5d6ffpayload.binTa5d6ff"
Te6edf3allowedTff7b72.Td2a8ffwrite_bytesTb4b4b4(Ta5d6ffbTa5d6ff"Ta5d6ffdataTa5d6ff"Tb4b4b4)
Te6edf3identity_file Tff7b72= Te6edf3tmp_path Tff7b72/ Ta5d6ff"Ta5d6ffidentityTa5d6ff"
Te6edf3identity_fileTff7b72.Td2a8ffwrite_bytesTb4b4b4(Ta5d6ffbTa5d6ff"Ta5d6ffsecret-keyTa5d6ff"Tb4b4b4)

T8b949e# Keep home jail separate from pytest tmp so sibling paths do not pass.
Te6edf3fake_home Tff7b72= Te6edf3tmp_path Tff7b72/ Ta5d6ff"Ta5d6ffhomeTa5d6ff"
Te6edf3fake_homeTff7b72.Td2a8ffmkdirTb4b4b4(Tb4b4b4)
Te6edf3monkeypatchTff7b72.Td2a8ffsetenvTb4b4b4(Ta5d6ff"Ta5d6ffHOMETa5d6ff"Tb4b4b4, Tffa657strTb4b4b4(Te6edf3fake_homeTb4b4b4)Tb4b4b4)
Te6edf3monkeypatchTff7b72.Td2a8ffsetattrTb4b4b4(
Te6edf3osTff7b72.Td2a8ffpathTb4b4b4, Ta5d6ff"Ta5d6ffexpanduserTa5d6ff"Tb4b4b4, Tff7b72lambda Te6edf3pTb4b4b4: Tffa657strTb4b4b4(Te6edf3fake_homeTb4b4b4) Tff7b72if Te6edf3p Tff7b72== Ta5d6ff"Ta5d6ff~Ta5d6ff" Tff7b72else Te6edf3p
Tb4b4b4)

Te6edf3outside_root Tff7b72= Te6edf3tmp_pathTff7b72.Td2a8ffparent Tff7b72/ Ta5d6ff"Ta5d6ffrncp-outside-rootTa5d6ff"
Te6edf3outside_rootTff7b72.Td2a8ffmkdirTb4b4b4(Te6edf3exist_okTff7b72=Tff7b72TrueTb4b4b4)
Te6edf3outside Tff7b72= Te6edf3outside_root Tff7b72/ Ta5d6ff"Ta5d6ffoutside-rncp.binTa5d6ff"
Te6edf3outsideTff7b72.Td2a8ffwrite_bytesTb4b4b4(Ta5d6ffbTa5d6ff"Ta5d6ffnopeTa5d6ff"Tb4b4b4)

Tff7b72assert Te6edf3handlerTff7b72.Td2a8ff_resolve_send_pathTb4b4b4(Tffa657strTb4b4b4(Te6edf3allowedTb4b4b4)Tb4b4b4)Tff7b72.Td2a8ffendswithTb4b4b4(Ta5d6ff"Ta5d6ffpayload.binTa5d6ff"Tb4b4b4)
Tff7b72with Te6edf3pytestTff7b72.Td2a8ffraisesTb4b4b4(Tf85149PermissionErrorTb4b4b4, Te6edf3matchTff7b72=Ta5d6ff"Ta5d6ffidentity private keyTa5d6ff"Tb4b4b4)Tb4b4b4:
Te6edf3handlerTff7b72.Td2a8ff_resolve_send_pathTb4b4b4(Tffa657strTb4b4b4(Te6edf3identity_fileTb4b4b4)Tb4b4b4)
Tff7b72with Te6edf3pytestTff7b72.Td2a8ffraisesTb4b4b4(Tf85149PermissionErrorTb4b4b4, Te6edf3matchTff7b72=Ta5d6ff"Ta5d6ffsend jailTa5d6ff"Tb4b4b4)Tb4b4b4:
Te6edf3handlerTff7b72.Td2a8ff_resolve_send_pathTb4b4b4(Tffa657strTb4b4b4(Te6edf3outsideTb4b4b4)Tb4b4b4)


Tff7b72def Td2a8fftest_request_client_ip_ignores_xff_without_trusted_proxyTb4b4b4(Tb4b4b4)Tb4b4b4:
Te6edf3req Tff7b72= Te6edf3SimpleNamespaceTb4b4b4(
Te6edf3headersTff7b72=Tb4b4b4{Ta5d6ff"Ta5d6ffX-Forwarded-ForTa5d6ff"Tb4b4b4: Ta5d6ff"Ta5d6ff203.0.113.9Ta5d6ff"Tb4b4b4}Tb4b4b4,
Te6edf3remoteTff7b72=Ta5d6ff"Ta5d6ff10.0.0.1Ta5d6ff"Tb4b4b4,
Tb4b4b4)
Tff7b72assert Te6edf3request_client_ipTb4b4b4(Te6edf3reqTb4b4b4) Tff7b72== Ta5d6ff"Ta5d6ff10.0.0.1Ta5d6ff"
Tff7b72assert Te6edf3request_client_ipTb4b4b4(Te6edf3reqTb4b4b4, Te6edf3trusted_proxy_cidrsTff7b72=Ta5d6ff"Ta5d6ff"Tb4b4b4) Tff7b72== Ta5d6ff"Ta5d6ff10.0.0.1Ta5d6ff"


Tff7b72def Td2a8fftest_request_client_ip_honors_xff_from_trusted_proxyTb4b4b4(Tb4b4b4)Tb4b4b4:
Te6edf3req Tff7b72= Te6edf3SimpleNamespaceTb4b4b4(
Te6edf3headersTff7b72=Tb4b4b4{Ta5d6ff"Ta5d6ffX-Forwarded-ForTa5d6ff"Tb4b4b4: Ta5d6ff"Ta5d6ff203.0.113.9, 10.0.0.2Ta5d6ff"Tb4b4b4}Tb4b4b4,
Te6edf3remoteTff7b72=Ta5d6ff"Ta5d6ff127.0.0.1Ta5d6ff"Tb4b4b4,
Tb4b4b4)
Tff7b72assert Te6edf3request_client_ipTb4b4b4(Te6edf3reqTb4b4b4, Te6edf3trusted_proxy_cidrsTff7b72=Ta5d6ff"Ta5d6ff127.0.0.1/32Ta5d6ff"Tb4b4b4) Tff7b72== Ta5d6ff"Ta5d6ff203.0.113.9Ta5d6ff"


Tff7b72def Td2a8fftest_request_client_ip_ignores_xff_from_untrusted_remoteTb4b4b4(Tb4b4b4)Tb4b4b4:
Te6edf3req Tff7b72= Te6edf3SimpleNamespaceTb4b4b4(
Te6edf3headersTff7b72=Tb4b4b4{Ta5d6ff"Ta5d6ffX-Forwarded-ForTa5d6ff"Tb4b4b4: Ta5d6ff"Ta5d6ff203.0.113.9Ta5d6ff"Tb4b4b4}Tb4b4b4,
Te6edf3remoteTff7b72=Ta5d6ff"Ta5d6ff198.51.100.1Ta5d6ff"Tb4b4b4,
Tb4b4b4)
Tff7b72assert Te6edf3request_client_ipTb4b4b4(Te6edf3reqTb4b4b4, Te6edf3trusted_proxy_cidrsTff7b72=Ta5d6ff"Ta5d6ff127.0.0.1/32Ta5d6ff"Tb4b4b4) Tff7b72== Ta5d6ff"Ta5d6ff198.51.100.1Ta5d6ff"


Tff7b72def Td2a8fftest_trusted_proxy_cidrs_env_overrideTb4b4b4(Te6edf3tmp_pathTb4b4b4, Te6edf3monkeypatchTb4b4b4)Tb4b4b4:
Te6edf3save_app_security_settingsTb4b4b4(Tffa657strTb4b4b4(Te6edf3tmp_pathTb4b4b4)Tb4b4b4, Tb4b4b4{Ta5d6ff"Ta5d6fftrusted_proxy_cidrsTa5d6ff"Tb4b4b4: Ta5d6ff"Ta5d6ff10.0.0.1/32Ta5d6ff"Tb4b4b4}Tb4b4b4)
Te6edf3monkeypatchTff7b72.Td2a8ffsetenvTb4b4b4(Ta5d6ff"Ta5d6ffMESHCHAT_TRUSTED_PROXIESTa5d6ff"Tb4b4b4, Ta5d6ff"Ta5d6ff127.0.0.1/32Ta5d6ff"Tb4b4b4)
Tff7b72assert Te6edf3get_trusted_proxy_cidrsTb4b4b4(Tffa657strTb4b4b4(Te6edf3tmp_pathTb4b4b4)Tb4b4b4) Tff7b72== Ta5d6ff"Ta5d6ff127.0.0.1/32Ta5d6ff"


Tff7b72def Td2a8fftest_is_path_within_dir_prefix_collisionTb4b4b4(Tb4b4b4)Tb4b4b4:
Tff7b72assert Tff7b72not Te6edf3is_path_within_dirTb4b4b4(
Ta5d6ff"Ta5d6ff/tmp/storage/database-backups_old/x.zipTa5d6ff"Tb4b4b4,
Ta5d6ff"Ta5d6ff/tmp/storage/database-backupsTa5d6ff"Tb4b4b4,
Tb4b4b4)


Tff7b72def Td2a8fftest_resolve_database_restore_path_jailsTb4b4b4(Te6edf3mock_appTb4b4b4, Te6edf3tmp_pathTb4b4b4)Tb4b4b4:
Te6edf3storage Tff7b72= Te6edf3tmp_path Tff7b72/ Ta5d6ff"Ta5d6ffidstorageTa5d6ff"
Te6edf3snaps Tff7b72= Te6edf3storage Tff7b72/ Ta5d6ff"Ta5d6ffsnapshotsTa5d6ff"
Te6edf3snapsTff7b72.Td2a8ffmkdirTb4b4b4(Te6edf3parentsTff7b72=Tff7b72TrueTb4b4b4)
Te6edf3good Tff7b72= Te6edf3snaps Tff7b72/ Ta5d6ff"Ta5d6ffok.zipTa5d6ff"
Te6edf3goodTff7b72.Td2a8ffwrite_bytesTb4b4b4(Ta5d6ffbTa5d6ff"Ta5d6ffPKTa5d6ff"Tb4b4b4)
Te6edf3evil Tff7b72= Te6edf3tmp_path Tff7b72/ Ta5d6ff"Ta5d6ffevil.zipTa5d6ff"
Te6edf3evilTff7b72.Td2a8ffwrite_bytesTb4b4b4(Ta5d6ffbTa5d6ff"Ta5d6ffPKTa5d6ff"Tb4b4b4)
Te6edf3mock_appTff7b72.Td2a8ffstorage_path Tff7b72= Tffa657strTb4b4b4(Te6edf3storageTb4b4b4)
Tff7b72assert Te6edf3mock_appTff7b72.Td2a8ff_resolve_database_restore_pathTb4b4b4(Ta5d6ff"Ta5d6ffok.zipTa5d6ff"Tb4b4b4) Tff7b72== Te6edf3osTff7b72.Td2a8ffpathTff7b72.Td2a8ffrealpathTb4b4b4(
Tffa657strTb4b4b4(Te6edf3goodTb4b4b4)
Tb4b4b4)
Tff7b72assert Te6edf3mock_appTff7b72.Td2a8ff_resolve_database_restore_pathTb4b4b4(Tffa657strTb4b4b4(Te6edf3evilTb4b4b4)Tb4b4b4) Tff7b72is Tff7b72None
Tff7b72assert Te6edf3mock_appTff7b72.Td2a8ff_resolve_database_restore_pathTb4b4b4(Tffa657strTb4b4b4(Te6edf3goodTb4b4b4)Tb4b4b4) Tff7b72== Te6edf3osTff7b72.Td2a8ffpathTff7b72.Td2a8ffrealpathTb4b4b4(
Tffa657strTb4b4b4(Te6edf3goodTb4b4b4)
Tb4b4b4)


──────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────